// gcc -o rt_test rt_test.c -lpthread

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
#include <sys/mman.h>
#include <time.h>
#include <string.h>

// 线程优先级（范围通常是1-99，数值越大优先级越高）
#define RT_PRIORITY 50
// 线程周期（微秒）
#define PERIOD_US 100000  // 100ms

// 实时线程函数
void *rt_thread_function(void *arg) {
    struct timespec ts;
    struct timespec sleep_time;
    int count = 0;

    // 初始化时钟
    clock_gettime(CLOCK_MONOTONIC, &ts);

    // 设置周期唤醒时间
    sleep_time.tv_sec = 0;
    sleep_time.tv_nsec = PERIOD_US * 1000;  // 转换为纳秒

    printf("实时线程启动 - 优先级: %d, 周期: %d us\n", RT_PRIORITY, PERIOD_US);
    printf("计数 | 时间(ms)\n");
    printf("----------------\n");

    // 周期性任务循环
    while (count < 20) {  // 运行20个周期后退出
        // 计算当前时间（毫秒）
        struct timespec current;
        clock_gettime(CLOCK_MONOTONIC, &current);
        long long elapsed_ms = (current.tv_sec - ts.tv_sec) * 1000 +
                              (current.tv_nsec - ts.tv_nsec) / 1000000;

        // 打印计数和时间
        printf("%5d | %lld\n", count, elapsed_ms);
        count++;

        // 等待下一个周期（使用绝对时间确保周期准确）
        ts.tv_nsec += sleep_time.tv_nsec;
        ts.tv_sec += ts.tv_nsec / 1000000000;
        ts.tv_nsec %= 1000000000;

        clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, NULL);
    }

    printf("实时线程完成\n");
    return NULL;
}

int main() {
    pthread_t rt_thread;
    pthread_attr_t attr;
    struct sched_param param;
    int ret;

    // 锁定内存防止页面交换（实时性重要措施）
    if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
        perror("mlockall failed");
        return EXIT_FAILURE;
    }

    // 初始化线程属性
    ret = pthread_attr_init(&attr);
    if (ret != 0) {
        fprintf(stderr, "pthread_attr_init failed: %s\n", strerror(ret));
        return EXIT_FAILURE;
    }

    // 设置线程调度策略为实时FIFO
    ret = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
    if (ret != 0) {
        fprintf(stderr, "pthread_attr_setschedpolicy failed: %s\n", strerror(ret));
        return EXIT_FAILURE;
    }

    // 设置线程优先级
    param.sched_priority = RT_PRIORITY;
    ret = pthread_attr_setschedparam(&attr, &param);
    if (ret != 0) {
        fprintf(stderr, "pthread_attr_setschedparam failed: %s\n", strerror(ret));
        return EXIT_FAILURE;
    }

    // 设置线程继承调度属性
    ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
    if (ret != 0) {
        fprintf(stderr, "pthread_attr_setinheritsched failed: %s\n", strerror(ret));
        return EXIT_FAILURE;
    }

    // 创建实时线程
    ret = pthread_create(&rt_thread, &attr, rt_thread_function, NULL);
    if (ret != 0) {
        fprintf(stderr, "pthread_create failed: %s\n", strerror(ret));
        return EXIT_FAILURE;
    }

    // 等待线程完成
    ret = pthread_join(rt_thread, NULL);
    if (ret != 0) {
        fprintf(stderr, "pthread_join failed: %s\n", strerror(ret));
        return EXIT_FAILURE;
    }

    // 清理
    pthread_attr_destroy(&attr);
    munlockall();

    return EXIT_SUCCESS;
}